home *** CD-ROM | disk | FTP | other *** search
/ PC Plus SuperCD (UK) 1998 May / PCPlus May 1998=disk A.iso / CPLUS45 / BC45 / OCFSRC.PAK / TYPELIB.CPP < prev   
Encoding:
C/C++ Source or Header  |  1995-08-29  |  38.3 KB  |  1,214 lines

  1. //
  2. //----------------------------------------------------------------------------
  3. // ObjectComponents
  4. // (C) Copyright 1994 by Borland International, All Rights Reserved
  5. //
  6. //   TServedObject implementation and OLE Type library generation
  7. //----------------------------------------------------------------------------
  8. #include <ocf/ocfpch.h>
  9. #include <ocf/appdesc.h>
  10. #include <osl/inlines.h>
  11.  
  12. #if defined(BI_PLAT_WIN32)
  13. # define OLE_TYPELIB_FILE L"stdole32.tlb"
  14. #elif defined(BI_PLAT_WIN16)
  15. # define OLE_TYPELIB_FILE "stdole.tlb"
  16. #endif
  17.  
  18. //____________________________________________________________________________
  19. //
  20. // TServedObject implementation
  21. //____________________________________________________________________________
  22.  
  23. TServedObjectCreator::TServedObjectCreator(TAppDescriptor& appDesc)
  24. : AppDesc(appDesc), AppObject(0) {}
  25.  
  26. TUnknown* TServedObjectCreator::CreateObject(TObjectDescriptor objDesc,
  27.                                        IUnknown* outer)
  28. {
  29.   TServedObject* ifc = AppDesc.FindServed(objDesc);
  30.   if (!ifc)
  31.     ifc = new TServedObject(objDesc, *this, outer);
  32.   if (!AppObject)
  33.     AppObject = ifc;
  34.   return ifc;
  35. }
  36.  
  37. IDispatch* TServedObjectCreator::CreateDispatch(TObjectDescriptor objDesc,
  38.                                  IUnknown* outer)
  39. {
  40.   TServedObject* obj = AppDesc.FindServed(objDesc);
  41.   if (!obj)
  42.     obj = new TServedObject(objDesc, *this, outer);
  43.   if (!AppObject)
  44.     AppObject = obj;
  45.   return *obj;
  46. }
  47.  
  48. void TServedObjectCreator::Attach(TServedObject& obj)
  49. {
  50.   AppDesc.AddServed(obj);
  51.   ++ObjCount;
  52. }
  53.  
  54. void TServedObjectCreator::Detach(TServedObject& obj)
  55. {
  56.   AppDesc.RemoveServed(obj);
  57.   if (--ObjCount == 0)
  58.     delete this;
  59. }
  60.  
  61. const GUID __cdecl IID_TServedObject = {0x02A101L,0,0,{0xC0,0,0,0,0,0,0,0x46}};
  62.  
  63. DEFINE_QI_OLEBASE(IDispatch,      0x20400L)
  64. DEFINE_QI_OLEBASE(ITypeInfo,      0x20401L)
  65.  
  66. DEFINE_COMBASES2(TServedCOM, IDispatch, ITypeInfo)
  67.  
  68. HRESULT TServedObject::QueryObject(const GUID far& iid, void far* far* pif)
  69. {
  70.   if (iid == IID_TServedObject) {
  71.     *pif = this;       // return actual pointer to this object
  72.     return HR_NOERROR; // non-interface returned, no AddRef(), do not Release
  73.   }
  74.   return TServedCOM::QueryObject(iid,pif);  // query inherited bases
  75. }
  76.  
  77. TServedObject::TServedObject(TObjectDescriptor& objDesc,
  78.                              TServedObjectCreator& creator,
  79.                              IUnknown* outer)
  80. :
  81.   Object(const_cast<void*>(objDesc.Object)), Destruct(objDesc.Destruct),
  82.   Creator(creator), Class(objDesc.Class)
  83. {
  84.   SetOuter(outer ? outer
  85.        : &objDesc.Class->Aggregate(const_cast<void*>(objDesc.Object), *this));
  86.   ReqLang = creator.AppDesc.GetAppLang();  // do we really need to initialize here?
  87.   creator.Attach(*this);
  88.   RootObject = objDesc.MostDerived();
  89. } // note: RefCnt = 0 on creation, will ++ in TAutoVal operator(IDispatch*)
  90.  
  91. TServedObject::~TServedObject()
  92. {
  93.   if (Object && Destruct != TObjectDescriptor::Quiet) {
  94.     TAutoCommand* cmdobj;
  95.     try {
  96.       cmdobj = Class->GetDestructor()(Object, Destruct);
  97.       cmdobj->Invoke();
  98.     }
  99.     catch(TXAuto&) {
  100.       // we can't indicate any error here
  101.     }
  102.     delete cmdobj;
  103.   }
  104.   Creator.Detach(*this);
  105. }
  106.  
  107. // IDispatch implementation
  108.  
  109. HRESULT _IFUNC
  110. TServedObject::GetTypeInfoCount(unsigned int far* pctinfo)
  111. {
  112.   *pctinfo = 1;
  113.   return HR_NOERROR;
  114. }
  115.  
  116. HRESULT _IFUNC
  117. TServedObject::GetTypeInfo(unsigned int /*itinfo*/, LCID lcid,
  118.                            ITypeInfo* far* pptinfo)
  119. {
  120.   ReqLang = LANGIDFROMLCID(lcid);
  121.   *pptinfo = static_cast<ITypeInfo*>(this);
  122.   AddRef();
  123.   return HR_NOERROR;
  124. }
  125.  
  126. HRESULT _IFUNC
  127. TServedObject::GetIDsOfNames(const IID far& riid, OLECHAR far* far* names,
  128.                           unsigned int cNames, LCID lcid, DISPID far* dispIds)
  129. {
  130.   if (riid != IID_NULL)
  131.     return HR_DISP_UNKNOWNINTERFACE;
  132.  
  133.   HRESULT retval = HR_NOERROR;
  134.   TAutoSymbol* symbol;
  135.   for (int i = 0; i < cNames; i++) {
  136.     dispIds[i] = -1;
  137.     if (i == 0) {
  138.       symbol = Class->Lookup(OleStr(names[0]), LANGIDFROMLCID(lcid),
  139.                              asAnyCommand, dispIds[0]);
  140.       if (!symbol)
  141.         retval = HR_DISP_UNKNOWNNAME;
  142.     }
  143.     else if (symbol) {
  144.       if (!Class->LookupArg(OleStr(names[i]), LANGIDFROMLCID(lcid), symbol, dispIds[i]))
  145.         retval = HR_DISP_UNKNOWNNAME;
  146.     }
  147.   }
  148.   return retval;
  149. }
  150.  
  151. HRESULT _IFUNC
  152. TServedObject::Invoke(DISPID dispidMember, const IID far& /*riid*/, LCID lcid,
  153.                       unsigned short wFlags, DISPPARAMS far* dispparams,
  154.                       VARIANT far* varResult, EXCEPINFO far* exceptInfo,
  155.                       unsigned int far* retArgErr)
  156. {
  157.   ObjectPtr object = Object;  // make copy in case of this pointer adjustment
  158.   if (!object)      // check if C++ object still exists
  159.     return HR_DISP_MEMBERNOTFOUND;
  160.   TAutoStack stack(dispparams->rgvarg, lcid, dispparams->cArgs,
  161.                    dispparams->cNamedArgs, dispparams->rgdispidNamedArgs, this);
  162.   stack.Symbol = Class->FindId((short)dispidMember, object);
  163.   if (!stack.Symbol)
  164.     return HR_DISP_MEMBERNOTFOUND;
  165.   if (!stack.Symbol->TestFlag(wFlags)) // check attr bits for supported type
  166.     return HR_DISP_MEMBERNOTFOUND;
  167.   if (wFlags & (DISPATCH_PROPERTYPUT | DISPATCH_PROPERTYPUTREF))
  168.     varResult = 0;
  169.   if ((stack.ArgSymbolCount=Class->GetArgCount(*stack.Symbol)) +
  170.   ((wFlags&(DISPATCH_PROPERTYPUT|DISPATCH_PROPERTYPUTREF))!=0) < stack.ArgCount)
  171.     return HR_DISP_BADPARAMCOUNT;
  172.  
  173.   switch(Class->Dispatch(object, Creator, *this, wFlags, stack,
  174.                          (TAutoVal far*)varResult)) {
  175.   case TXAuto::xNoError:
  176.     return HR_NOERROR;
  177.  
  178.   case TXAuto::xNotIDispatch:
  179.   case TXAuto::xForeignIDispatch:
  180.     return HR_DISP_BADVARTYPE;
  181.  
  182.   case TXAuto::xValidateFailure:
  183.     *retArgErr = stack.CurrentArg;
  184.     return HR_DISP_OVERFLOW;
  185.  
  186.   case TXAuto::xConversionFailure:
  187.   case TXAuto::xTypeMismatch:
  188.     *retArgErr = stack.CurrentArg;
  189.     return HR_DISP_TYPEMISMATCH;
  190.  
  191.   case TXAuto::xNoArgSymbol:
  192.     *retArgErr = stack.CurrentArg;
  193.     return HR_DISP_PARAMNOTFOUND;
  194.  
  195.   case TXAuto::xParameterMissing:
  196.   case TXAuto::xNoDefaultValue:
  197.     return HR_DISP_PARAMNOTOPTIONAL;
  198.  
  199.   case TXAuto::xErrorStatus:
  200.     if (exceptInfo) {
  201.       exceptInfo->wCode = (unsigned short)stack.ErrorCode;
  202.       exceptInfo->wReserved = 0;
  203.       exceptInfo->bstrSource = ::SysAllocString(Creator.AppDesc.GetAppName(LANGIDFROMLCID(lcid)));
  204.       exceptInfo->bstrDescription = ::SysAllocString(stack.ErrorMsg);
  205.       exceptInfo->bstrHelpFile = 0;
  206.       exceptInfo->pfnDeferredFillIn = 0;
  207.       exceptInfo->scode = E_FAIL;  // how to get better code? matters?
  208.     }
  209.     return HR_DISP_EXCEPTION;
  210.  
  211.   case TXAuto::xExecutionFailure:
  212.   default:
  213.     return HR_DISP_OVERFLOW;  // no appropriate error for other
  214.   }
  215. }
  216.  
  217.  
  218. //----------------------------------------------------------------------------
  219. // ITypeInfo implementation
  220. //
  221.  
  222. HRESULT _IFUNC
  223. TServedObject::GetTypeAttr(TYPEATTR far* far* retTypeAttr)
  224. {
  225.   Class->CountCommands();    // force update of symbol counts;
  226.   TYPEATTR* ta = (TYPEATTR*)new char[sizeof(TYPEATTR)];
  227.   memset(ta, 0, sizeof(TYPEATTR));
  228.   Creator.AppDesc.GetClassId(Class, ta->guid);
  229.   ta->lcid = ReqLang;
  230.   ta->typekind = TKIND_DISPATCH;
  231.   ta->wTypeFlags = Class->GetTypeFlags();
  232.   ta->cFuncs = Class->FunctionCount;
  233.   ta->cVars  = Class->VariableCount;
  234.   ta->wMajorVerNum = Creator.AppDesc.GetVersionField(0);
  235.   ta->wMinorVerNum = Creator.AppDesc.GetVersionField(1);
  236.   *retTypeAttr = ta;
  237.   return HR_NOERROR;
  238. }
  239.  
  240. void _IFUNC
  241. TServedObject::ReleaseTypeAttr(TYPEATTR far* ptypeattr)
  242. {
  243.   delete [] (char*)ptypeattr;
  244. }
  245.  
  246. HRESULT _IFUNC
  247. TServedObject::GetFuncDesc(unsigned int index, FUNCDESC far* far* retDesc)
  248. {
  249.   int cmdId = 0;   // must initialize, FindFunction recursively adjusts it
  250.   TAutoSymbol* sym = Class->FindFunction(index, cmdId);
  251.   if (!sym || !retDesc)
  252.     return HR_INVALIDARG;
  253.   int kind = (sym->GetFlags() & asOleType);
  254.   bool isPropSet = kind==INVOKE_PROPERTYPUT || kind==INVOKE_PROPERTYPUTREF;
  255.   int argCount = Class->GetArgCount(*sym);
  256.   int asize = sizeof(ELEMDESC) * (argCount+isPropSet) + sizeof(FUNCDESC);
  257.   int size = (argCount+1) * sizeof(TYPEDESC) + asize;
  258.   FUNCDESC* fd = (FUNCDESC*)new char[size];
  259.   TYPEDESC* ptrtd = (TYPEDESC*)((char*)fd + asize); // for indirected types
  260.   memset(fd, 0, size);
  261.   fd->cParams = short(argCount + isPropSet);
  262.   fd->lprgelemdescParam = (ELEMDESC*)(fd+1);
  263.   fd->memid = cmdId;
  264.   fd->funckind = FUNC_DISPATCH;
  265.   fd->invkind = (INVOKEKIND)kind;
  266.   fd->callconv = CC_CDECL;  // need to set to prevent typelib.dll asserts
  267.   fd->cScodes = -1;
  268.   ELEMDESC* argDesc = &fd->elemdescFunc;
  269.   if (isPropSet){
  270.     argDesc->tdesc.vt = VT_EMPTY;
  271.     argDesc = (ELEMDESC*)(fd+1);
  272.   }
  273.   for (int argIndex = 0; argIndex <= argCount; argIndex++, sym++, ptrtd++) {
  274.     TAutoClass* cls = sym->GetClass();
  275.     if (cls) {
  276.       argDesc->tdesc.vt = VT_USERDEFINED;
  277.       argDesc->tdesc.hreftype = (HREFTYPE)cls;
  278.     } else if (sym->IsEnum()) {
  279.       argDesc->tdesc.vt = atString;  // expose enumerated type as string
  280.     } else if (sym->IsArray()) {
  281.       argDesc->tdesc.vt = VT_SAFEARRAY;
  282.       argDesc->tdesc.lptdesc = ptrtd;
  283.       ptrtd->vt = sym->GetDataType();
  284.     } else if (sym->IsByRef()) {
  285.       argDesc->tdesc.vt = VT_PTR;
  286.       argDesc->tdesc.lptdesc = ptrtd;
  287.       ptrtd->vt = sym->GetDataType();
  288.     } else {
  289.       argDesc->tdesc.vt = sym->GetDataType();
  290.     }
  291.     argDesc++;
  292.     if (argIndex == 0) {
  293.       if (!isPropSet)
  294.         argDesc = (ELEMDESC*)(fd+1);
  295.     } else {
  296.       if (sym->Doc)    // argument optional if has default string
  297.         fd->cParamsOpt++;
  298.     }
  299.   }
  300.   *retDesc = fd;
  301.   return HR_NOERROR;
  302. }
  303.  
  304. void _IFUNC
  305. TServedObject::ReleaseFuncDesc(FUNCDESC far* pfuncdesc)
  306. {
  307.   delete [] (char*)pfuncdesc;
  308. }
  309.  
  310. HRESULT _IFUNC
  311. TServedObject::GetVarDesc(unsigned int index, VARDESC far* far* retDesc)
  312. {
  313.   VARDESC* vd = (VARDESC*)new char[sizeof(VARDESC) + sizeof(TYPEDESC)];
  314.   TYPEDESC* ptrtd = (TYPEDESC*)((char*)vd + sizeof(VARDESC));
  315.   memset(vd, 0, sizeof(VARDESC)+sizeof(TYPEDESC));
  316.   int cmdId = 0;   // must initialize, FindVariable recursively adjusts it
  317.   TAutoSymbol* sym = Class->FindVariable(index, cmdId);
  318.   if (!sym || !retDesc)
  319.     return HR_INVALIDARG;
  320.   TAutoClass* cls = sym->GetClass();
  321.   vd->memid = cmdId;
  322.   vd->varkind = VAR_DISPATCH;
  323.   if (cls) {
  324.     vd->elemdescVar.tdesc.vt = VT_USERDEFINED;
  325.     vd->elemdescVar.tdesc.hreftype = (HREFTYPE)cls;
  326.   } else if (sym->IsEnum()) {
  327.       vd->elemdescVar.tdesc.vt = atString;  // expose enumerated type as string
  328.   } else if (sym->IsArray()) {
  329.     vd->elemdescVar.tdesc.vt = VT_SAFEARRAY;
  330.     vd->elemdescVar.tdesc.lptdesc = ptrtd;
  331.     ptrtd->vt = sym->GetDataType();
  332.   } else if (sym->IsByRef()) {
  333.     vd->elemdescVar.tdesc.vt = VT_PTR;
  334.     vd->elemdescVar.tdesc.lptdesc = ptrtd;
  335.     ptrtd->vt = sym->GetDataType();
  336.   } else {
  337.     vd->elemdescVar.tdesc.vt = sym->GetDataType();
  338.   }
  339.   *retDesc = vd;
  340.   return HR_NOERROR;
  341. }
  342.  
  343. void _IFUNC
  344. TServedObject::ReleaseVarDesc(VARDESC far* pvardesc)
  345. {
  346.   delete pvardesc;
  347.   return;
  348. }
  349.  
  350. HRESULT _IFUNC
  351. TServedObject::GetNames(MEMBERID memid, BSTR far* rgbstrNames,
  352.                         unsigned int cMaxNames, unsigned int far* pcNames)
  353. {
  354.   ObjectPtr noObj = 0;
  355.   TAutoSymbol* sym = Class->FindId((short)memid, noObj);
  356.   if (!sym)
  357.     return HR_DISP_MEMBERNOTFOUND;
  358.   int nameCount = Class->GetArgCount(*sym) + 1;
  359.   if (nameCount > cMaxNames)
  360.     nameCount = cMaxNames;
  361.   for (int index = 0; index < nameCount; index++, sym++)
  362.     rgbstrNames[index] = ::SysAllocString(sym->Name.Translate(ReqLang));
  363.   *pcNames = nameCount;
  364.   return HR_NOERROR;
  365. }
  366.  
  367. HRESULT _IFUNC
  368. TServedObject::GetIDsOfNames(OLECHAR far* far* names, uint cNames,
  369.                              MEMBERID far* retIds)
  370. {
  371.   HRESULT retval = HR_NOERROR;
  372.   TAutoSymbol* symbol;
  373.   for (int i = 0; i < cNames; i++) {
  374.     retIds[i] = -1;
  375.     if (i == 0) {
  376.       symbol = Class->Lookup(OleStr(names[0]), ReqLang, asAnyCommand, retIds[0]);
  377.       if (!symbol)
  378.         retval = HR_DISP_UNKNOWNNAME;
  379.     }
  380.     else if (symbol) {
  381.       if (!Class->LookupArg(OleStr(names[i]), ReqLang, symbol, retIds[i]))
  382.         retval = HR_DISP_UNKNOWNNAME;
  383.     }
  384.   }
  385.   return retval;
  386. }
  387.  
  388. HRESULT _IFUNC
  389. TServedObject::Invoke(void far* pvInstance, MEMBERID memid,
  390.                       unsigned short wFlags, DISPPARAMS far *dispparams,
  391.                       VARIANT far *varResult, EXCEPINFO far *exceptinfo,
  392.                       unsigned int far *retArgErr)
  393. {
  394.   if (Object)   // cannot invoke if active object obtained from IDispatch ifc
  395.     return HR_TYPE_INVALIDSTATE;
  396.   Object = (void*)pvInstance; // going on faith that caller has valid instance
  397.   RootObject = ::MostDerived(Object, Class->GetTypeInfo());
  398.   HRESULT stat = Invoke(memid, IID_NULL, ReqLang, wFlags, dispparams,
  399.                         varResult, exceptinfo, retArgErr);
  400.   Object = 0;
  401.   RootObject = 0;
  402.   return stat;
  403. }
  404.  
  405. HRESULT _IFUNC
  406. TServedObject::GetDocumentation(MEMBERID memid,
  407.                                 BSTR far* retName, BSTR far* retDoc,
  408.                                 ulong far* retHelpContext,
  409.                                 BSTR far* retHelpFile)
  410. {
  411.   TAutoSymbol* sym;
  412.   if (memid == -1) {       // request info on type library itself
  413.     sym = Class->GetClassSymbol();
  414.   } else {
  415.     ObjectPtr noObj = 0;
  416.     if ((sym = Class->FindId((short)memid, noObj)) == 0)
  417.       return HR_DISP_MEMBERNOTFOUND;
  418.   }
  419.   if (retName)
  420.     *retName = ::SysAllocString(sym->Name.Translate(ReqLang));
  421.   if (retDoc)
  422.     *retDoc  = ::SysAllocString(sym->Doc.Translate(ReqLang));
  423.   if (retHelpContext)
  424.     *retHelpContext = sym->HelpId;
  425.   if (retHelpFile)
  426.     *retHelpFile = ::SysAllocString(Creator.AppDesc.GetHelpFile(ReqLang));
  427.   return HR_NOERROR;
  428. }
  429.  
  430. HRESULT _IFUNC
  431. TServedObject::CreateInstance(IUnknown* /*punkOuter*/, const IID far& /*riid*/,
  432.                               void far* far* /*ppvObj*/)
  433. {
  434.   return HR_TYPE_WRONGTYPEKIND;
  435. }
  436.  
  437. HRESULT _IFUNC
  438. TServedObject::GetContainingTypeLib(ITypeLib* far* retLib,
  439.                                                 unsigned int far* retIndex)
  440. {
  441.   *retLib = Creator.AppDesc.GetTypeLibrary();
  442.   if (retIndex)
  443.     *retIndex = Creator.AppDesc.GetClassIndex(Class);
  444.   return HR_NOERROR;  // is it really possible to fail?
  445. }
  446.  
  447. HRESULT _IFUNC
  448. TServedObject::GetRefTypeInfo(HREFTYPE hreftype, ITypeInfo* far* retInfo)
  449. {
  450.   TAutoClass* cls = (TAutoClass*)hreftype;
  451.   if (Creator.AppDesc.GetClassIndex(cls) == -1)  // validate pointer to avoid crash
  452.     return HR_TYPE_WRONGTYPEKIND;
  453.   *retInfo = Creator.AppDesc.CreateITypeInfo(*cls);
  454.   return HR_NOERROR;
  455. }
  456.  
  457. // The following methods of ITypeInfo are not relevant for Dispatch interfaces
  458.  
  459. HRESULT _IFUNC
  460. TServedObject::GetTypeComp(ITypeComp* far* /*pptcomp*/)
  461. {
  462.   return HR_TYPE_LIBNOTREGISTERED;
  463. }
  464.  
  465. HRESULT _IFUNC
  466. TServedObject::GetMops(MEMBERID /*memid*/, BSTR far*)
  467. {
  468.   return HR_TYPE_WRONGTYPEKIND;
  469. }
  470.  
  471. HRESULT _IFUNC
  472. TServedObject::GetImplTypeFlags(unsigned int /*index*/, int far*)
  473. {
  474.   return HR_TYPE_WRONGTYPEKIND;
  475. }
  476.  
  477. HRESULT _IFUNC
  478. TServedObject::GetRefTypeOfImplType(unsigned int /*index*/,
  479.                                     HREFTYPE far* /*phreftype*/)
  480. {
  481.   return HR_TYPE_WRONGTYPEKIND;
  482. }
  483.  
  484. HRESULT _IFUNC
  485. TServedObject::GetDllEntry(MEMBERID /*memid*/, INVOKEKIND /*invkind*/,
  486.                            BSTR far* /*pbstrDllName*/, BSTR far* /*pbstrName*/,
  487.                            unsigned short far* /*pwOrdinal*/)
  488. {
  489.   return HR_TYPE_WRONGTYPEKIND;
  490. }
  491.  
  492. HRESULT _IFUNC
  493. TServedObject::AddressOfMember(MEMBERID /*memid*/, INVOKEKIND /*invkind*/,
  494.                                void far* far* /*ppv*/)
  495. {
  496.   return HR_TYPE_WRONGTYPEKIND;
  497. }
  498.  
  499. //____________________________________________________________________________
  500. //
  501. // TypeLibrary generation
  502. //____________________________________________________________________________
  503.  
  504. // local class to hold ICreateTypeLib interface pointers for each class
  505.  
  506. struct TOleCreateInfo {
  507.   int FuncCount;
  508.   int VarCount;
  509.   int ImplCount;
  510.   TYPEKIND TypeKind;
  511.   ITypeInfo*       OurTypeInfo;  // our type info implementation
  512.   ITypeInfo*       OleTypeInfo;  // type info obtained from ICreatTypeInfo
  513.   ICreateTypeInfo* CreateInfo;   // interface obtained from ICreateTypeLib
  514.   TOleCreateInfo() : OurTypeInfo(0), OleTypeInfo(0), CreateInfo(0) {}
  515.  ~TOleCreateInfo();
  516. };
  517.  
  518. TOleCreateInfo::~TOleCreateInfo()
  519. {
  520.   if (OurTypeInfo)
  521.     OurTypeInfo->Release();
  522.   if (OleTypeInfo)
  523.     OleTypeInfo->Release();
  524.   if (CreateInfo)
  525.     CreateInfo->Release();
  526. }
  527.  
  528. struct TOleCreateList {
  529.   int             Count;
  530.   ITypeLib*       TypeLib;
  531.   const char far* FileName;
  532.   TOleCreateInfo* List;
  533.   ITypeLib*       OleLib;
  534.   ITypeComp*      OleComp;
  535.   ITypeInfo*      OleInfo;
  536.   ICreateTypeLib* CreateLib;
  537.   TLIBATTR far*   LibAttr;
  538.   TYPEATTR far*   TypeAttr;
  539.   ITypeInfo*      AttrTypeInfo;  // valid only when TypeAttr!=0, not refcnt'd
  540.   TBSTR* FuncNames;              // temporary transfer of BSTR name arrays
  541.  
  542.   TOleCreateList(ITypeLib* typeLib, const char far* fileName);
  543.   void FixupTypeDescRef(int typeIndex, TYPEDESC far& typeDesc);
  544.   void Close(const char far* helpDir);
  545.   void Clear();
  546.  ~TOleCreateList() {Clear();}
  547. };
  548.  
  549. TOleCreateList::TOleCreateList(ITypeLib* typeLib, const char far* fileName)
  550. :
  551.   TypeLib(typeLib),
  552.   FileName(fileName),
  553.   OleLib(0), OleComp(0), OleInfo(0),
  554.   CreateLib(0), TypeAttr(0), LibAttr(0), List(0), FuncNames(0)
  555. {
  556.   TBSTR libName;
  557.   TBSTR libDoc;
  558.   TBSTR helpFile;
  559.   ulong helpId;
  560.   TypeLib->AddRef();
  561.   OLECALL(::LoadTypeLib(OLE_TYPELIB_FILE, &OleLib), "Load stdole.tlb");
  562.   OLECALL(OleLib->GetTypeComp(&OleComp), "GetTypeComp");
  563.   ITypeComp* tempComp;     // required as reference arg, but always set to 0
  564.   OLECALL(OleComp->BindType(OleText("IDispatch"),
  565.                             ::LHashValOfName(0, OleText("IDispatch")),
  566.                             &OleInfo,&tempComp), "BindType");
  567.   OLECALL(TypeLib->GetLibAttr(&LibAttr), "GetLibAttr");
  568.   OLECALL(TypeLib->GetDocumentation(-1, libName, libDoc, &helpId, helpFile),
  569.                                          "GetDocumentation for library");
  570.   OLECALL(::CreateTypeLib(LibAttr->syskind, OleStr((char far*)FileName), &CreateLib), "CreateTypeLib");
  571.   OLECALL(CreateLib->SetGuid(LibAttr->guid), "Set TypeLib GUID");
  572.   OLECALL(CreateLib->SetLcid(LibAttr->lcid), "Set TypeLib language");
  573.   OLECALL(CreateLib->SetLibFlags(LibAttr->wLibFlags), "Set TypeLib flags");
  574.   if (!!libName)
  575.     OLECALL(CreateLib->SetName(libName), "Set TypeLib name");
  576.   if (!!libDoc)
  577.     OLECALL(CreateLib->SetDocString(libDoc), "Set TypeLib doc");
  578.   if (!!helpFile)
  579.   {
  580.     OLECALL(CreateLib->SetHelpFileName(helpFile), "SetHelpFileName");
  581.     OLECALL(CreateLib->SetHelpContext(helpId), "HelpContext");
  582.   }
  583.   OLECALL(CreateLib->SetVersion(LibAttr->wMajorVerNum,
  584.                                 LibAttr->wMinorVerNum), "Set TypeLib version");
  585.   //  allocate all ITypeInfo's upfront to force consistent references
  586.   Count = TypeLib->GetTypeInfoCount();
  587.   List = new TOleCreateInfo[Count];
  588.   for (int nInfo = 0; nInfo < Count; nInfo++) {
  589.     TOleCreateInfo& info = List[nInfo];
  590.     ICreateTypeInfo* newInfo;
  591.     OLECALL(TypeLib->GetTypeInfo(nInfo, &AttrTypeInfo), "GetTypeInfo");
  592.     info.OurTypeInfo = AttrTypeInfo;
  593.     OLECALL(info.OurTypeInfo->GetTypeAttr(&TypeAttr), "GetTypeAttr");
  594.     OLECALL(TypeLib->GetDocumentation(nInfo,libName,libDoc,&helpId,helpFile),
  595.                                              "GetDocumentation for TypeInfo");
  596.     OLECALL(CreateLib->CreateTypeInfo(libName, TypeAttr->typekind, &newInfo),
  597.                                    "Create CreateTypeInfo");
  598.     info.CreateInfo = newInfo;
  599.     OLECALL(newInfo->QueryInterface(IID_ITypeInfo,
  600.            (void far*far*)&info.OleTypeInfo), "QueryInterface for ITypeInfo");
  601.     if (!!libDoc)
  602.       OLECALL(newInfo->SetDocString(libDoc), "Set TypeInfo doc");
  603.     OLECALL(newInfo->SetHelpContext(helpId), "SetHelpContext");
  604.     OLECALL(newInfo->SetVersion(TypeAttr->wMajorVerNum,
  605.                                   TypeAttr->wMinorVerNum),"Set TypeInfo version");
  606.     OLECALL(newInfo->SetGuid(TypeAttr->guid), "SetTypeInfo GUID");
  607.     OLECALL(newInfo->SetTypeFlags(TypeAttr->wTypeFlags), "SetTypeFlags");
  608.     if (TypeAttr->typekind == TKIND_DISPATCH) {
  609.       HREFTYPE hreftype;
  610.       OLECALL(newInfo->AddRefTypeInfo(OleInfo, &hreftype), "AddRefTypeInfo");
  611.       OLECALL(newInfo->AddImplType(0, hreftype), "AddImplType");
  612.     }
  613.     info.TypeKind  = TypeAttr->typekind;
  614.     info.FuncCount = TypeAttr->cFuncs;
  615.     info.VarCount  = TypeAttr->cVars;
  616.     info.ImplCount = TypeAttr->cImplTypes;
  617.     info.OurTypeInfo->ReleaseTypeAttr(TypeAttr), TypeAttr = 0;
  618.   }
  619. }
  620.  
  621. void TOleCreateList::Close(const char far* helpDir)
  622. {
  623.   OLECALL(CreateLib->SaveAllChanges(), "Write and close TypeLib file");
  624.   CreateLib->Release();
  625.   CreateLib = 0;
  626.   OLECALL(::RegisterTypeLib(TypeLib,
  627.                             OleStr((char far*)FileName),
  628.                             OleStr((char far*)helpDir)),
  629.           "Register type library");
  630. }
  631.  
  632. void TOleCreateList::Clear()
  633. {
  634.   delete[] List;  // releases all interface pointers
  635.   delete[] FuncNames;  // in case exception thrown while in use
  636.   if (LibAttr)
  637.     TypeLib->ReleaseTLibAttr(LibAttr);
  638.   if (TypeAttr)
  639.     AttrTypeInfo->ReleaseTypeAttr(TypeAttr);
  640.   if (OleInfo)
  641.     OleInfo->Release();
  642.   if (OleComp)
  643.     OleComp->Release();
  644.   if (OleLib)
  645.     OleLib->Release();
  646.   if (CreateLib)
  647.     CreateLib->Release();
  648.   TypeLib->Release();  // finally release typelib called at constructor
  649. }
  650.  
  651. void
  652. TOleCreateList::FixupTypeDescRef(int typeIndex, TYPEDESC far& typeDesc)
  653. {
  654.   if (typeDesc.vt == VT_USERDEFINED) {
  655.     ITypeInfo* refInfo;
  656.     OLECALL(List[typeIndex].OurTypeInfo->GetRefTypeInfo(typeDesc.hreftype,
  657.                                                  &refInfo), "GetRefTypeInfo");
  658.     refInfo->Release();   // ok to release here, we're only using its pointer
  659.     for (int nInfo = 0; nInfo < Count; nInfo++) {
  660.        if (List[nInfo].OurTypeInfo == refInfo) {
  661.          OLECALL(List[typeIndex].CreateInfo->AddRefTypeInfo(List[nInfo].OleTypeInfo,
  662.                                        &typeDesc.hreftype), "AddRefTypeInfo");
  663.          return;
  664.        }
  665.     }
  666.     OLECALL(HR_TYPE_ELEMENTNOTFOUND, "Unknown reference type");
  667.   }
  668. }
  669.  
  670. void
  671. TAppDescriptor::WriteTypeLibrary(TLangId lang, const char far* file)
  672. {
  673.   TBSTR libName;
  674.   TBSTR libDoc;
  675.   ulong helpId;
  676.   FUNCDESC far* funcDesc = 0;
  677.   VARDESC far* varDesc = 0;
  678.   TOleCreateList typeList(new TTypeLibrary(*this, lang), file);
  679.   for (int nInfo = 0; nInfo < typeList.Count; nInfo++) {
  680.     TOleCreateInfo& curInfo = typeList.List[nInfo];
  681.     ITypeInfo* typeInfo = curInfo.OurTypeInfo;
  682.     ICreateTypeInfo* newInfo  = curInfo.CreateInfo;
  683.     for (int index = 0; index < curInfo.FuncCount; index++) {
  684.       OLECALL(typeInfo->GetFuncDesc(index, &funcDesc), "GetFuncDesc");
  685.       OLECALL(typeInfo->GetDocumentation(funcDesc->memid, libName, libDoc,
  686.                               &helpId, 0), "Get method name and doc");
  687.       for (int nArg = funcDesc->cParams; nArg-- >=0; ) {
  688.         ELEMDESC far* elem = nArg < 0 ? &funcDesc->elemdescFunc
  689.                                       : &funcDesc->lprgelemdescParam[nArg];
  690.         typeList.FixupTypeDescRef(nInfo, elem->tdesc);
  691.       }
  692.       OLECALL(newInfo->AddFuncDesc(index, funcDesc), "AddFuncDesc");
  693.       unsigned nNames = funcDesc->cParams + 1;
  694.       typeList.FuncNames = new TBSTR[nNames];
  695.       OLECALL(typeInfo->GetNames(funcDesc->memid, (BSTR*)typeList.FuncNames,
  696.                               nNames, &nNames), "Get method parameter names");
  697.       OLECALL(newInfo->SetFuncAndParamNames(index, (BSTR*)typeList.FuncNames,
  698.                                        nNames), "Set method parameter names");
  699.       delete[] typeList.FuncNames;
  700.       typeList.FuncNames = 0;
  701.       if (!!libDoc)
  702.         OLECALL(newInfo->SetFuncDocString(index, libDoc),"Set method doc");
  703.       OLECALL(newInfo->SetFuncHelpContext(index, helpId), "HelpContext");
  704.       typeInfo->ReleaseFuncDesc(funcDesc), funcDesc = 0;
  705.     }
  706.     for (index = 0; index < curInfo.VarCount; index++) {
  707.       OLECALL(typeInfo->GetVarDesc(index, &varDesc), "GetVarDesc");
  708.       OLECALL(typeInfo->GetDocumentation(varDesc->memid, libName, libDoc,
  709.                              &helpId, 0), "Get propery name and doc");
  710.       typeList.FixupTypeDescRef(nInfo, varDesc->elemdescVar.tdesc);
  711.       OLECALL(newInfo->AddVarDesc(index, varDesc), "AddVarDesc");
  712.       OLECALL(newInfo->SetVarName(index, libName),"Set property name");
  713.       if (!!libDoc)
  714.         OLECALL(newInfo->SetVarDocString(index, libDoc),"Set property doc");
  715.       OLECALL(newInfo->SetVarHelpContext(index, helpId), "HelpContext");
  716.       typeInfo->ReleaseVarDesc(varDesc), varDesc = 0;
  717.     }
  718.     if (curInfo.TypeKind == TKIND_COCLASS) {
  719.       for (index = 0; index < curInfo.ImplCount; index++) {
  720.         HREFTYPE hreftype;
  721.         ITypeInfo* refInfo;
  722.         OLECALL(typeInfo->GetRefTypeOfImplType(index, &hreftype),"GetCoClassRef");
  723.         OLECALL(typeInfo->GetRefTypeInfo(hreftype, &refInfo), "GetCoClassTypeInfo");
  724.         refInfo->Release();   // ok to release here, only using its pointer
  725.         for (int iInfo = 0; iInfo < typeList.Count; iInfo++) {
  726.           if (typeList.List[iInfo].OurTypeInfo == refInfo) {
  727.             OLECALL(newInfo->AddRefTypeInfo(typeList.List[iInfo].OleTypeInfo, &hreftype), "AddRefTypeInfo");
  728.             OLECALL(newInfo->AddImplType(index, hreftype), "AddImplType");
  729.             int implflags;
  730.             OLECALL(typeInfo->GetImplTypeFlags(index, &implflags), "GetImplTypeFlags");
  731.             OLECALL(newInfo->SetImplTypeFlags(index, implflags), "SetImplTypeFlags");
  732.           }
  733.         }
  734.       }
  735.     }
  736.     OLECALL(newInfo->LayOut(), "Layout typeinfo");
  737.   }
  738.   const char* helpDir = RegInfo.Lookup("helpdir");
  739.   if (!helpDir || *helpDir == 0) {
  740.     char path [_MAX_PATH];
  741.     char drive[_MAX_DRIVE];
  742.     char dir  [_MAX_DIR];
  743.     ::GetModuleFileName(AppInstance, path, sizeof(path));
  744.     _splitpath(path, drive, dir, 0, 0);
  745.     _makepath (path, drive, dir, 0, 0);
  746.     helpDir = path;
  747.   }
  748.   typeList.Close(helpDir);
  749.  
  750.   int iGuid = 0;   // first pass for app, second for debug app if present
  751.   do {
  752.     char buf[80];
  753.     strcpy(buf, "CLSID\\");
  754.     strcat(buf, AppClassId[iGuid]);
  755.     strcat(buf, "\\TypeLib");
  756.     ::RegSetValue(HKEY_CLASSES_ROOT,buf,REG_SZ, AppClassId[LibGuidOffset], 0);
  757.     iGuid ^= DebugGuidOffset;    // remains 0 if no debug guid assigned
  758.   } while (iGuid);
  759. }
  760.  
  761. //____________________________________________________________________________
  762. //
  763. // TTypeLibrary implementation
  764. //____________________________________________________________________________
  765.  
  766. TTypeLibrary::TTypeLibrary(TAppDescriptor& appDesc, TLangId lang)
  767.                : AppDesc(appDesc), Lang(lang), RefCnt(0)
  768. {
  769.   CoClassFlags = 0;
  770.   CoClassImplCount = 0;
  771.   TAutoClass::TAutoClassRef* ref = AppDesc.ClassList;
  772.   for (int index = 0; index < AppDesc.ClassCount; index++, ref++) {
  773.     TAutoClass* cls = ref->Class;
  774.     int    implFlags = cls->GetImplTypeFlags();
  775.     uint16 typeFlags = cls->GetCoClassFlags();
  776.     if (implFlags != 0 || typeFlags != 0) {
  777.       CoClassImplCount++;
  778.       CoClassFlags |= typeFlags;
  779.     }
  780.   }
  781. }
  782.  
  783. TTypeLibrary::~TTypeLibrary()
  784. {
  785.   if (AppDesc.TypeLib == this)
  786.     AppDesc.TypeLib = 0;    // remove pointer to this
  787.   if (RefCnt > 0)
  788.     ::CoDisconnectObject(this,0);   // should not normally happen
  789. }
  790.  
  791. ITypeInfo*
  792. TTypeLibrary::CreateCoClassInfo()
  793. {
  794.   ITypeInfo* ifc = new TCoClassInfo(AppDesc, CoClassFlags, CoClassImplCount);
  795.   ifc->AddRef();
  796.   return ifc;
  797. }
  798.  
  799. HRESULT _IFUNC
  800. TTypeLibrary::QueryInterface(const IID far& riid, void far* far* retIface)
  801. {
  802.   if (riid == IID_IUnknown || riid == IID_ITypeLib) {
  803.     AddRef();
  804.     *retIface = (IUnknown*)this;
  805.     return HR_NOERROR;
  806.   }
  807.   *retIface = 0;
  808.   return HR_NOINTERFACE;
  809. }
  810.  
  811. unsigned long _IFUNC
  812.  
  813. TTypeLibrary::AddRef()
  814. {
  815.   return ++RefCnt;
  816. }
  817.  
  818. unsigned long _IFUNC
  819. TTypeLibrary::Release()
  820. {
  821.   if (--RefCnt != 0)
  822.     return RefCnt;
  823.   delete this;
  824.   return 0;
  825. }
  826.  
  827. unsigned int _IFUNC
  828. TTypeLibrary::GetTypeInfoCount()
  829. {
  830.   return AppDesc.GetClassCount() + (CoClassImplCount > 0);  // +1 for CoClass
  831. }
  832.  
  833. HRESULT _IFUNC
  834. TTypeLibrary::GetTypeInfo(unsigned index, ITypeInfo* far* retInfo)
  835. {
  836.   if (CoClassImplCount > 0 && index == AppDesc.GetClassCount()) {
  837.     *retInfo = CreateCoClassInfo();
  838.   } else {
  839.     TAutoClass* cls = AppDesc.GetAutoClass(index);
  840.     if (!cls)
  841.       return HR_TYPE_ELEMENTNOTFOUND;
  842.     *retInfo = AppDesc.CreateITypeInfo(*cls);
  843.   }
  844.   return HR_NOERROR;
  845. }
  846.  
  847. HRESULT _IFUNC
  848. TTypeLibrary::GetTypeInfoType(unsigned index, TYPEKIND far* retKind)
  849. {
  850.   unsigned int count = AppDesc.GetClassCount();
  851.   if (index > count)
  852.     return HR_TYPE_ELEMENTNOTFOUND;
  853.   *retKind = (index == count ? TKIND_COCLASS : TKIND_DISPATCH);
  854.   return HR_NOERROR;
  855. }
  856.  
  857. HRESULT _IFUNC
  858. TTypeLibrary::GetTypeInfoOfGuid(const GUID far& guid, ITypeInfo* far* retInfo)
  859. {
  860.   if (AppDesc.AppClassId.GetOffset(guid) == 0) {
  861.     *retInfo = CreateCoClassInfo();
  862.   } else {
  863.     TAutoClass* cls = AppDesc.GetAutoClass(guid);
  864.     if (!cls)
  865.       return HR_TYPE_ELEMENTNOTFOUND;
  866.     *retInfo = AppDesc.CreateITypeInfo(*cls);
  867.   }
  868.   return HR_NOERROR;
  869. }
  870.  
  871. HRESULT _IFUNC
  872. TTypeLibrary::GetLibAttr(TLIBATTR far* far* retAttr)
  873. {
  874.   TLIBATTR* libAttr = new TLIBATTR;
  875.   memset(libAttr, 0, sizeof(TLIBATTR));
  876. #if defined(BI_PLAT_WIN32)
  877.   libAttr->syskind = SYS_WIN32;
  878. #elif defined(BI_PLAT_WIN16)
  879.   libAttr->syskind = SYS_WIN16;
  880. #endif
  881.   libAttr->lcid = Lang;
  882.   AppDesc.GetClassId(0, libAttr->guid);
  883.   libAttr->wMajorVerNum = AppDesc.GetVersionField(0);
  884.   libAttr->wMinorVerNum = AppDesc.GetVersionField(1);
  885.   *retAttr = libAttr;
  886.   return HR_NOERROR;
  887. }
  888.  
  889. void _IFUNC
  890. TTypeLibrary::ReleaseTLibAttr(TLIBATTR far* attr)
  891. {
  892.   delete attr;
  893. }
  894.  
  895. HRESULT _IFUNC
  896. TTypeLibrary::GetTypeComp(ITypeComp* far* /*retComp*/)
  897. {
  898.   return HR_TYPE_UNSUPFORMAT;
  899. }
  900.  
  901. HRESULT _IFUNC
  902. TTypeLibrary::GetDocumentation(int index, BSTR far* retName,
  903.                                BSTR far* retDoc,
  904.                                ulong far* retHelpContext,
  905.                                BSTR far* retHelpFile)
  906. {
  907.   if (retHelpFile)
  908.      *retHelpFile = ::SysAllocString(AppDesc.GetHelpFile(Lang));
  909.   if (retHelpContext)
  910.      *retHelpContext = 0;
  911.   if (index == -1 || index == AppDesc.GetClassCount()) { // library itself
  912.     if (retName)
  913.       *retName = ::SysAllocString(AppDesc.GetAppName(Lang));
  914.     if (retDoc)
  915.       *retDoc  = ::SysAllocString(AppDesc.GetAppDoc(Lang));
  916.     if (retHelpContext)
  917.       *retHelpContext = 0;
  918.   } else {
  919.     TAutoClass* cls = AppDesc.GetAutoClass(index);
  920.     if (!cls)
  921.       return HR_TYPE_ELEMENTNOTFOUND;
  922.     if (retName)
  923.       *retName = ::SysAllocString(cls->GetName(Lang));
  924.     if (retDoc)
  925.       *retDoc  = ::SysAllocString(cls->GetDoc(Lang));
  926.     if (retHelpContext)
  927.       *retHelpContext = cls->GetHelpId();
  928.   }
  929.   return HR_NOERROR;
  930. }
  931.  
  932. HRESULT _IFUNC
  933. TTypeLibrary::IsName(OLECHAR far* nameBuf, ulong /*hashVal*/, int far* retFound)
  934. {
  935.   TAutoClass::TAutoClassRef* ref = AppDesc.ClassList;
  936.   for (int index = 0; index < AppDesc.ClassCount; index++, ref++) {
  937.     TAutoClass* cls = ref->Class;
  938.     // not clear from doc if we should check names of classes as well as members
  939.     long id;
  940.     TAutoSymbol* sym = cls->Lookup(OleStr(nameBuf), Lang, asOleType, id);
  941.     if (sym) {
  942. #if defined(BI_OLECHAR_WIDE)
  943.       lstrcpyW(nameBuf, OleStr(sym->Name));
  944. #else
  945.       strcpy(nameBuf, sym->Name);
  946. #endif
  947.       *retFound = 1;
  948.       return HR_NOERROR;
  949.     }
  950.   }
  951.   return ResultFromScode(TYPE_E_ELEMENTNOTFOUND);
  952. }
  953.  
  954. HRESULT _IFUNC
  955. TTypeLibrary::FindName(OLECHAR far* nameBuf, ulong /*lHashVal*/,
  956.                        ITypeInfo* far* retInfo, MEMBERID far* retId,
  957.                        unsigned short far* inoutCount)
  958. {
  959.   unsigned short found = 0;
  960.   TAutoClass::TAutoClassRef* ref = AppDesc.ClassList;
  961.   for (int index = 0; index < AppDesc.ClassCount && found < *inoutCount;
  962.                       index++, ref++) {
  963.     TAutoClass* cls = ref->Class;
  964.     long id;
  965.     TAutoSymbol* sym = cls->Lookup(OleStr(nameBuf), Lang, asOleType, id);
  966.     if (sym) {
  967.       retId[found] = id;
  968.       retInfo[found] = AppDesc.CreateITypeInfo(*cls);
  969.       found++;
  970.     }
  971.   }
  972.   *inoutCount = found;
  973.   return found ? HR_NOERROR : HR_TYPE_ELEMENTNOTFOUND;
  974. }
  975.  
  976. //____________________________________________________________________________
  977. //
  978. // TCoClassInfo implementation
  979. //____________________________________________________________________________
  980.  
  981. TCoClassInfo::TCoClassInfo(TAppDescriptor& appDesc, uint16 typeFlags, int implCount)
  982. : AppDesc(appDesc), RefCnt(0), TypeFlags(typeFlags), ImplCount(implCount)
  983. {
  984.   ImplList = new unsigned[implCount];
  985.   TAutoClass::TAutoClassRef* ref = AppDesc.ClassList;
  986.   int iapp     = -1;
  987.   int ievent   = -1;
  988.   Default      = -1;
  989.   DefaultEvent = -1;
  990.   int iclass   =  0;
  991.   for (int index = 0; iclass < implCount; index++, ref++) {
  992.     TAutoClass* cls = ref->Class;
  993.     int    implFlags = cls->GetImplTypeFlags();
  994.     uint16 typeFlags = cls->GetCoClassFlags();
  995.     if (implFlags || typeFlags) {
  996.       if (implFlags & IMPLTYPEFLAG_FSOURCE) {
  997.         ievent = iclass;
  998.         if (implFlags & IMPLTYPEFLAG_FDEFAULT)
  999.           DefaultEvent = iclass;
  1000.       } else {
  1001.         if (typeFlags & TYPEFLAG_FAPPOBJECT)
  1002.           iapp = iclass;
  1003.         if (implFlags & IMPLTYPEFLAG_FDEFAULT)
  1004.           Default = iclass;
  1005.       }
  1006.       ImplList[iclass++] = index;
  1007.     }
  1008.   }
  1009.   if (Default == -1)
  1010.     Default = iapp;
  1011.   if (DefaultEvent == -1)
  1012.     DefaultEvent = ievent;
  1013. }
  1014.  
  1015. TCoClassInfo::~TCoClassInfo()
  1016. {
  1017.   delete ImplList;
  1018. }
  1019.  
  1020. HRESULT _IFUNC
  1021. TCoClassInfo::QueryInterface(const IID far& riid, void far* far* retIface)
  1022. {
  1023.   if (riid == IID_IUnknown || riid == IID_ITypeInfo) {
  1024.     AddRef();
  1025.     *retIface = (IUnknown*)this;
  1026.     return HR_NOERROR;
  1027.   }
  1028.   *retIface = 0;
  1029.   return HR_NOINTERFACE;
  1030. }
  1031.  
  1032. unsigned long _IFUNC
  1033.  
  1034. TCoClassInfo::AddRef()
  1035. {
  1036.   return ++RefCnt;
  1037. }
  1038.  
  1039. unsigned long _IFUNC
  1040. TCoClassInfo::Release()
  1041. {
  1042.   if (--RefCnt != 0)
  1043.     return RefCnt;
  1044.   delete this;
  1045.   return 0;
  1046. }
  1047.  
  1048. HRESULT _IFUNC
  1049. TCoClassInfo::GetTypeAttr(TYPEATTR far* far* retTypeAttr)
  1050. {
  1051.   TYPEATTR* ta = (TYPEATTR*)new char[sizeof(TYPEATTR)];
  1052.   memset(ta, 0, sizeof(TYPEATTR));
  1053.   ta->guid = AppDesc.AppClassId;
  1054.   ta->lcid = AppDesc.GetAppLang();
  1055.   ta->typekind = TKIND_COCLASS;
  1056.   ta->cImplTypes = (unsigned short)ImplCount;
  1057.   ta->wMajorVerNum = AppDesc.GetVersionField(0);
  1058.   ta->wMinorVerNum = AppDesc.GetVersionField(1);
  1059.   ta->wTypeFlags = TypeFlags;
  1060.   *retTypeAttr = ta;
  1061.   return HR_NOERROR;
  1062. }
  1063.  
  1064. void _IFUNC
  1065. TCoClassInfo::ReleaseTypeAttr(TYPEATTR far* ptypeattr)
  1066. {
  1067.   delete [] (char*)ptypeattr;
  1068. }
  1069.  
  1070. HRESULT _IFUNC
  1071. TCoClassInfo::GetDocumentation(MEMBERID memid,
  1072.                                 BSTR far* retName, BSTR far* retDoc,
  1073.                                 ulong far* retHelpContext,
  1074.                                 BSTR far* retHelpFile)
  1075. {
  1076.   if (retHelpFile)
  1077.     *retHelpFile = ::SysAllocString(AppDesc.GetHelpFile(AppDesc.GetAppLang()));
  1078.   if (memid == -1) {       // request info on type library itself
  1079.     if (retName)
  1080.       *retName = ::SysAllocString(AppDesc.GetAppName(AppDesc.GetAppLang()));
  1081.     if (retDoc)
  1082.       *retDoc  = ::SysAllocString(AppDesc.GetAppDoc(AppDesc.GetAppLang()));
  1083.     if (retHelpContext)
  1084.       *retHelpContext = 0;
  1085.   } else {
  1086.     return HR_TYPE_WRONGTYPEKIND;
  1087.   }
  1088.   return HR_NOERROR;
  1089. }
  1090.  
  1091. HRESULT _IFUNC
  1092. TCoClassInfo::CreateInstance(IUnknown* /*punkOuter*/, const IID far& /*riid*/,
  1093.                               void far* far* /*ppvObj*/)
  1094. {
  1095.   return HR_TYPE_WRONGTYPEKIND;
  1096. }
  1097.  
  1098. HRESULT _IFUNC
  1099. TCoClassInfo::GetContainingTypeLib(ITypeLib* far* retLib,
  1100.                                                 unsigned int far* retIndex)
  1101. {
  1102.   *retLib = AppDesc.GetTypeLibrary();
  1103.   if (retIndex)
  1104.     *retIndex = AppDesc.GetClassCount();
  1105.   return HR_NOERROR;
  1106. }
  1107.  
  1108. HRESULT _IFUNC
  1109. TCoClassInfo::GetRefTypeInfo(HREFTYPE hreftype, ITypeInfo* far* retInfo)
  1110. {
  1111.   TAutoClass* cls = (TAutoClass*)hreftype;
  1112.   if (AppDesc.GetClassIndex(cls) == -1)  // validate pointer to avoid crash
  1113.     return HR_TYPE_WRONGTYPEKIND;
  1114.   *retInfo = AppDesc.CreateITypeInfo(*cls);
  1115.   return HR_NOERROR;
  1116. }
  1117.  
  1118. HRESULT _IFUNC
  1119. TCoClassInfo::GetImplTypeFlags(unsigned int index, int far* retflags)
  1120. {
  1121.   TAutoClass* cls = index<ImplCount ? AppDesc.GetAutoClass(ImplList[index]):0;
  1122.   if (!cls)
  1123.     return HR_TYPE_ELEMENTNOTFOUND;
  1124.   int implFlags = cls->GetImplTypeFlags();
  1125.   if (implFlags & IMPLTYPEFLAG_FSOURCE) {
  1126.     if (index == DefaultEvent)
  1127.       implFlags |= IMPLTYPEFLAG_FDEFAULT;
  1128.   } else {
  1129.     if (index == Default)
  1130.       implFlags |= IMPLTYPEFLAG_FDEFAULT;
  1131.   }
  1132.   *retflags = implFlags;
  1133.   return HR_NOERROR;
  1134. }
  1135.  
  1136. HRESULT _IFUNC
  1137. TCoClassInfo::GetRefTypeOfImplType(unsigned int index,
  1138.                                     HREFTYPE far* retreftype)
  1139. {
  1140.   TAutoClass* cls = index<ImplCount ? AppDesc.GetAutoClass(ImplList[index]):0;
  1141.   *retreftype = (HREFTYPE)cls;
  1142.   return cls ? HR_NOERROR : HR_TYPE_ELEMENTNOTFOUND;
  1143. }
  1144.  
  1145. // The following methods of ITypeInfo are not relevant for a COCLASS typeinfo
  1146.  
  1147. HRESULT _IFUNC
  1148. TCoClassInfo::GetFuncDesc(unsigned int, FUNCDESC far* far*)
  1149. {
  1150.   return HR_TYPE_WRONGTYPEKIND;
  1151. }
  1152.  
  1153. void _IFUNC
  1154. TCoClassInfo::ReleaseFuncDesc(FUNCDESC far*)
  1155. {
  1156. }
  1157.  
  1158. HRESULT _IFUNC
  1159. TCoClassInfo::GetVarDesc(unsigned int, VARDESC far* far*)
  1160. {
  1161.   return HR_TYPE_WRONGTYPEKIND;
  1162. }
  1163.  
  1164. void _IFUNC
  1165. TCoClassInfo::ReleaseVarDesc(VARDESC far*)
  1166. {
  1167. }
  1168.  
  1169. HRESULT _IFUNC
  1170. TCoClassInfo::GetNames(MEMBERID, BSTR far*, unsigned int, unsigned int far*)
  1171. {
  1172.   return HR_TYPE_WRONGTYPEKIND;
  1173. }
  1174.  
  1175. HRESULT _IFUNC
  1176. TCoClassInfo::GetIDsOfNames(OLECHAR far* far*, uint, MEMBERID far*)
  1177. {
  1178.   return HR_TYPE_WRONGTYPEKIND;
  1179. }
  1180.  
  1181. HRESULT _IFUNC
  1182. TCoClassInfo::Invoke(void far*, MEMBERID, unsigned short, DISPPARAMS far*,
  1183.                       VARIANT far*, EXCEPINFO far*, unsigned int far*)
  1184. {
  1185.   return HR_TYPE_WRONGTYPEKIND;
  1186. }
  1187.  
  1188. HRESULT _IFUNC
  1189. TCoClassInfo::GetTypeComp(ITypeComp* far*)
  1190. {
  1191.   return HR_TYPE_LIBNOTREGISTERED;
  1192. }
  1193.  
  1194. HRESULT _IFUNC
  1195. TCoClassInfo::GetMops(MEMBERID, BSTR far*)
  1196. {
  1197.   return HR_TYPE_WRONGTYPEKIND;
  1198. }
  1199.  
  1200. HRESULT _IFUNC
  1201. TCoClassInfo::GetDllEntry(MEMBERID, INVOKEKIND, BSTR far*, BSTR far*,
  1202.                           unsigned short far*)
  1203. {
  1204.   return HR_TYPE_WRONGTYPEKIND;
  1205. }
  1206.  
  1207. HRESULT _IFUNC
  1208. TCoClassInfo::AddressOfMember(MEMBERID, INVOKEKIND, void far* far*)
  1209. {
  1210.   return HR_TYPE_WRONGTYPEKIND;
  1211. }
  1212.  
  1213.  
  1214.